#include <pthread.h>

#include <log4cxx/logger.h>
#include <log4cxx/xml/domconfigurator.h>

#include <list>
#include <iostream>

#include "MutexLocker.h"
#include "ResourcePool.h"
#include "SMsg.h"
#include "INIParser.h"

#define THREAD_NUM 100
#define LOGGER_NAME "shadow.sutil.test"
#define LOG_CONF_FILE "sutil_test_log.xml"
#define TEST_INI_FILE "./test.ini"

using std::list;
using std::cout;
using std::endl;

log4cxx::LoggerPtr g_logger = log4cxx::Logger::getLogger(LOGGER_NAME);

typedef struct _TEST_MUTEX_LOCKER_ROUTINE_ARG {
	pthread_mutex_t mutex;
	list<int> l;
} TEST_MUTEX_LOCKER_ROUTINE_ARG;

void * test_mutex_locker_routine(void * p_arg) {
	LOG4CXX_INFO(g_logger, "enter test mutex locker routine");
       	TEST_MUTEX_LOCKER_ROUTINE_ARG * p = (TEST_MUTEX_LOCKER_ROUTINE_ARG *)p_arg;
	list<int> & the_list = p->l;
	for (int i = 0; i < 30; i++) {
		MutexLocker locker1(&p->mutex);
		locker1.lock();
		the_list.push_back(i);
		LOG4CXX_INFO(g_logger, "push item:" << i << " to list");
	}
	MutexLocker locker2(&p->mutex);
	sleep(1);
	locker2.lock();
	for (list<int>::iterator iter = the_list.begin(); the_list.end() != iter; iter++) {
		LOG4CXX_INFO(g_logger, "iteratate through the list, item:" << *iter)
	}
//	locker.unlock();
	return NULL;
}

int test_mutex_locker() {

	TEST_MUTEX_LOCKER_ROUTINE_ARG arg;
	pthread_mutex_init(&arg.mutex, NULL);

	pthread_t threads[THREAD_NUM];
	for (int i = 0; i < THREAD_NUM; i++) {
		pthread_create(&threads[i], NULL, test_mutex_locker_routine, &arg);
	}
	for(int i = 0; i < THREAD_NUM; i++) {
		pthread_join(threads[i], NULL);
	}

	return 1;


}

void * test_resource_pool_routine(void * arg) {
		ResourcePool * res_pool = (ResourcePool *)arg;
		while (true) {
				int index = res_pool->acquire_resource();
				LOG4CXX_INFO(g_logger, "acquire resource index:" << index << ", from resource pool");
				sleep(1);
				res_pool->release_resource(index);
				LOG4CXX_INFO(g_logger, "release resource index:" << index << ", from resource pool");
		}
		return NULL;
}


int test_resource_pool() {
		ResourcePool res_pool;
		res_pool.init(10, -1);
		pthread_t threads[THREAD_NUM];
		for (int i = 0; i < THREAD_NUM; i++) {
				pthread_create(&threads[i], NULL, test_resource_pool_routine, &res_pool);
		}
		for(int i = 0; i < THREAD_NUM; i++) {
				pthread_join(threads[i], NULL);
		}
		return 1;
}

int test_smsg() {
		SMsg msg1, msg2, msg3;
		string s, key1, key2, value1, value2;
		key1 = "key=1&&\nx";
		value1 = "value=1&&;xx";
		key2 = "key=2";
		value2 = "value=2";
	
		int res = msg1.put(key1, value1);
		res = msg1.put(key2, value2);
		res = msg1.pack(s);
		cout << "msg1 pack, res:" << res << ", s:" << s << endl;
		res = msg2.unpack(s.c_str(), s.size());
		res = msg2.get_string_value(key1, value1);
		res = msg2.get_string_value(key2, value2);
		cout << "key1 value:" << value1 << endl;
		cout << "key2 value:" << value2 << endl;
		return 1;
}

int test_ini_parser() {
		INIParser ini_parser;
		ini_parser.parse(TEST_INI_FILE);
		map<string, StringMap> & contents = ini_parser.get_contents();
		for (map<string, StringMap>::const_iterator iter = contents.begin(); contents.end() != iter; iter++) {
				cout << "-----------------" << endl;
				cout << "session:" << iter->first << endl;
				for (StringMap::const_iterator iter1 = iter->second.begin(); iter->second.end() != iter1; iter1++) {
						cout << "key:" << iter1->first << ", value:" << iter1->second << endl;
				}
		}
		cout << "-----------------" << endl;
		int int_t;
		string session = "mysqld";
		string key = "table_cache";
		int res = ini_parser.get_int_value(session.c_str(), key.c_str(), int_t);
		cout << "session:" << session << ", key:" << key << ", value:" << int_t << ", res:" << res << endl ;
		string str_t;
		key = "query_cache_size";
		res = ini_parser.get_string_value(session.c_str(), key.c_str(), str_t);
		cout << "session:" << session << ", key:" << key << ", value:" << str_t <<", res:" << res << endl;
		return 1;
}

int main(int argc, char * argv[]) {
	
	log4cxx::xml::DOMConfigurator::configure(LOG_CONF_FILE);

//	test_mutex_locker();
//	test_resource_pool();
//	test_smsg();
	test_ini_parser();

	return 0;
}
